#pragma once

//#include <cstddef>
//#include <iterator>
namespace unstd{


template<typename T>
class NodeIndexFixed{
public:
	typedef int index_type;
	NodeIndexFixed();
	NodeIndexFixed(const T& val);
	NodeIndexFixed(const T& val, index_type next);
	//~NodeIndex();

	T value;
	index_type nextNodeIndex;
};

template<typename T>	
class FixedList_Iterator_Forward_Const
	: public std::iterator<std::forward_iterator_tag, T, std::ptrdiff_t,
		const T*, const T&>{
public:
	
	template<typename U, int A> 
	friend class FixedList;
	
	FixedList_Iterator_Forward_Const();
	FixedList_Iterator_Forward_Const(const FixedList_Iterator_Forward_Const & other);
	FixedList_Iterator_Forward_Const(NodeIndexFixed<T>  *list, int index);

	FixedList_Iterator_Forward_Const& operator ++();
	FixedList_Iterator_Forward_Const operator ++(int);

	template<typename T>
	friend bool operator ==(const FixedList_Iterator_Forward_Const& it1, const FixedList_Iterator_Forward_Const& it2);
	
	template<typename T>
	friend bool operator !=(const FixedList_Iterator_Forward_Const& it1, const FixedList_Iterator_Forward_Const& it2);
	
	reference operator *();

private:
	NodeIndexFixed<T>  *list;

	int currentNodeIndex;


};
template<typename T>	
class FixedList_Iterator_Forward
	: public std::iterator<std::forward_iterator_tag, T, std::ptrdiff_t,
		T*, T&>{
	
public:
	
	template<typename U, int A> 
	friend class FixedList;
	
	FixedList_Iterator_Forward();
	FixedList_Iterator_Forward(const FixedList_Iterator_Forward & other);
	FixedList_Iterator_Forward(NodeIndexFixed<T>  *list, int index);

	FixedList_Iterator_Forward& operator ++();
	FixedList_Iterator_Forward operator ++(int);

	template<typename T>
	friend bool operator ==(const FixedList_Iterator_Forward& it1, const FixedList_Iterator_Forward& it2);
	
	template<typename T>
	friend bool operator !=(const FixedList_Iterator_Forward& it1, const FixedList_Iterator_Forward& it2);
	
	reference operator *();

private:
	NodeIndexFixed<T>  *list;

	int currentNodeIndex;
};

template<typename T,int SIZE>
class FixedList
{

public:

	typedef typename T value_type;
	typedef typename T* pointer;
	typedef typename T& reference;
	typedef typename const T& const_reference;
	typedef typename ptrdiff_t difference_type;
	typedef typename size_t size_type;


	typedef typename FixedList_Iterator_Forward<T> iterator;
	typedef typename  FixedList_Iterator_Forward_Const<T> const_iterator;


	
	size_type length;
	int tail, head;
	int freeListHead;
//	CONSTRUCTORS 

	explicit FixedList( );
	//explicit SListVec( const Allocator& alloc = Allocator() );

	/*explicit SListVec( size_type count,
               const T& value = T(),
               const Allocator& alloc = Allocator());*/
	FixedList( const FixedList& other );
	//template <class InputIterator> 
	//SListVec( InputIterator first, InputIterator last, const Allocator& alloc = Allocator() );
	//


	//DESTRUCTORS
	~FixedList();

	/*----- OPERATORS -------*/
	FixedList& operator =(const FixedList& other);
	

	void assign( size_type count, const T& value );
	template< class InputIterator > void assign( InputIterator first, InputIterator last );

	
	/*----- ELEMENT ACCESS -------*/
	reference front();
	const_reference front() const;

	reference back();	
	const_reference back() const;

	/*----- ITERATORS -------*/
	iterator begin();
	const_iterator begin() const;
	iterator end();
	const_iterator end() const;

	/*------- CAPACITY ----------*/
	bool empty() const;
	size_type size() const;
	size_type max_size() const;

	/*------- MODIFIERS ----------*/
	void clear();
	
	iterator insert( iterator pos, const T& value );
	void insert( iterator pos, size_type count, const T& value );
	
	template <class InputIterator>
	void insert( iterator pos, InputIterator first, InputIterator last);

	iterator erase( iterator pos );
	iterator erase( iterator first, iterator last );

	void push_back( const T& value );
	void pop_back();
	void push_front( const T& value );
	void pop_front();

	void resize( size_type size, T value = T() );	
	void swap( FixedList& other );
private:

	NodeIndexFixed<T>  list[SIZE];
	
	int prevNodeIndex(int nodeIndex);	
	int prevNodeIndex(iterator node);
	void addNodeToFreeList(int nodeIndex);
	int popNodeFromFreeList(); //return index of first available element and remove index from free list
	void clearFreeList();
};
	
#include "FixedList.inl"
//#include "Foo.inl"
}